package com.engine.salary.biz;

import com.engine.common.util.ServiceUtil;
import com.engine.salary.entity.salaryBill.dto.SalarySendUserInfoDTO;
import com.engine.salary.entity.salaryBill.po.SalarySendRangeObj;
import com.engine.salary.entity.taxagent.dto.TaxAgentEmployeeTaxAgentDTO;
import com.engine.salary.mapper.salarybill.SalarySendRangeObjMapper;
import com.engine.salary.service.TaxAgentService;
import com.engine.salary.service.impl.TaxAgentServiceImpl;
import com.engine.salary.util.db.MapperProxyFactory;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.session.SqlSession;
import weaver.conn.mybatis.MyBatisFactory;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.engine.salary.constant.SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY;

public class SalarySendRangeObjBiz {
    private TaxAgentService getTaxAgentService() {
        return ServiceUtil.getService(TaxAgentServiceImpl.class);
    }

    private SalarySendRangeObjMapper getSalarySendRangeObjMapper() {
        return MapperProxyFactory.getProxy(SalarySendRangeObjMapper.class);
    }

    public  <R> R applyMapper(Function<SalarySendRangeObjMapper, R> mapper) {
        try (SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession()) {
            final SalarySendRangeObjMapper salarySendRangeObjMapper = sqlSession.getMapper(SalarySendRangeObjMapper.class);
            R apply = mapper.apply(salarySendRangeObjMapper);
            sqlSession.commit();
            return apply;
        }
    }

    public void runMapper(Consumer<SalarySendRangeObjMapper> mapper) {
        try (SqlSession sqlSession = MyBatisFactory.sqlSessionFactory.openSession()) {
            final SalarySendRangeObjMapper salarySendRangeObjMapper = sqlSession.getMapper(SalarySendRangeObjMapper.class);
            mapper.accept(salarySendRangeObjMapper);
            sqlSession.commit();
        }
    }

    public List<SalarySendUserInfoDTO> getSalarySendUserInfoDTOs(List<Long> employees) {
        List<SalarySendUserInfoDTO> userDTOs = new ArrayList<>();
        List<List<Long>> partition = Lists.partition(employees, 500);
        partition.forEach(l->{
            List<SalarySendUserInfoDTO> userInfos = getSalarySendRangeObjMapper().getUserInfoByEmployeeIds(l);
            userDTOs.addAll(userInfos);
        });

        Map<Long, SalarySendUserInfoDTO> userMap = userDTOs.stream()
                .collect(Collectors.toMap(SalarySendUserInfoDTO::getResourceId, Function.identity()));

        List<Long> employeeIds = userDTOs.stream()
                .map(SalarySendUserInfoDTO::getResourceId)
                .collect(Collectors.toList());
        Collection<TaxAgentEmployeeTaxAgentDTO> employeeAgents
                = getTaxAgentService().listAllTaxAgentsAsRange(employeeIds);
        for (TaxAgentEmployeeTaxAgentDTO employeeAgent : employeeAgents) {
            SalarySendUserInfoDTO info = userMap.get(employeeAgent.getEmployeeId());
            if (info != null) {
                if (CollectionUtils.isEmpty(info.getTaxAgentIds())) {
                    info.setTaxAgentIds(new ArrayList<>());
                }
                info.getTaxAgentIds().addAll(Optional.ofNullable(employeeAgent.getTaxAgentIds()).orElse(Collections.emptyList()));
            }
        }
        return userDTOs;
    }

    public void replaceAllByRangeId(Long rangeId, List<SalarySendRangeObj> rangeObjs) {
        runMapper(mapper -> {
            mapper.deleteByRangeIds(Collections.singletonList(rangeId), DEFAULT_TENANT_KEY);
            mapper.batchInsert(rangeObjs);
        });
    }
}
